package com.inplaceedit.client.activity.main.contact;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.google.gwt.core.client.GWT;
import com.google.gwt.editor.client.Editor;
import com.google.gwt.editor.client.LeafValueEditor;
import com.google.gwt.editor.client.SimpleBeanEditorDriver;
import com.google.gwt.editor.client.adapters.ListEditor;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.place.shared.PlaceController;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.inject.Inject;
import com.core.gwt.place.client.CompositeActivity;
import com.inplaceedit.client.place.ContactDetailsPlace;
import com.inplaceedit.client.place.ContactNewPlace;
import com.inplaceedit.client.place.HomePlace;
import com.inplaceedit.client.ui.contact.ContactNameEditor;
import com.inplaceedit.client.ui.phone.PhoneEditor;
import com.inplaceedit.shared.dto.CompanyDto;
import com.inplaceedit.shared.dto.ContactDto;
import com.inplaceedit.shared.dto.DtoFactory;
import com.inplaceedit.shared.dto.PhoneDto;
import com.inplaceedit.shared.webservice.CompanyRemoteServiceAsync;
import com.inplaceedit.shared.webservice.ContactRemoteServiceAsync;

public class ContactNewActivityImpl extends CompositeActivity implements
		ContactNewActivity {

	public static interface ObjectEditor extends Editor<ContactDto> {
		@Editor.Path("birthday")
		LeafValueEditor<Date> getBirthdayEditor();

		@Editor.Path("")
		ContactNameEditor getNameEditor();

		@Editor.Path("phoneList")
		ListEditor<PhoneDto, PhoneEditor> getPhoneListEditor();

		@Editor.Path("sex")
		LeafValueEditor<ContactDto.Sex> getSexSelector();
	}

	public static interface View extends IsWidget, ObjectEditor {
		public static interface Handler {
			void onCancel();

			void onSave();
		}

		void enableSave(boolean enabled);

		void setHandler(Handler handler);
	}

	interface ObjectEditorDriver extends
			SimpleBeanEditorDriver<ContactDto, ObjectEditor> {
	}

	@Inject
	private View view;
	@Inject
	ContactRemoteServiceAsync contactService;
	@Inject
	private CompanyRemoteServiceAsync companyService;
	@Inject
	PlaceController placeController;

	private final DtoFactory factory = GWT.create(DtoFactory.class);
	private final ObjectEditorDriver editorDriver = GWT
			.create(ObjectEditorDriver.class);
	private boolean done;

	private final View.Handler viewHandler = new View.Handler() {
		@Override
		public void onCancel() {
			done = true;
			placeController.goTo(new HomePlace());
		}

		@Override
		public void onSave() {
			final ContactDto object = editorDriver.flush();
			view.enableSave(false);
			contactService.save(object, new AsyncCallback<ContactDto>() {
				@Override
				public void onFailure(final Throwable caught) {
					GWT.log("", caught);
					view.enableSave(true);
				}

				@Override
				public void onSuccess(final ContactDto result) {
					done = true;
					final ContactDetailsPlace newPlace = new ContactDetailsPlace();
					newPlace.setId(result.getId());
					placeController.goTo(newPlace);
				}
			});

		}
	};

	private final ContactNameEditor.Handler nameEditorHandler = new ContactNameEditor.Handler() {
		@Override
		public void getCompanyList(
				final AsyncCallback<List<CompanyDto>> callback) {
			companyService.list(callback);
		}
	};

	@Override
	public String mayStop() {
		String warning = super.mayStop();
		if (warning == null && !done && editorDriver.isDirty()) {
			warning = "Discard changes?";
		}
		return warning;
	}

	@Override
	public void onCancel() {
		super.onCancel();
		detach();
	}

	@Override
	public void onStop() {
		super.onStop();
		detach();
	}

	@Override
	public void setPlace(final ContactNewPlace place) {
	}

	@Override
	public void start(final AcceptsOneWidget panel, final EventBus eventBus) {
		attach();

		view.getNameEditor().refresh();

		final ContactDto object = factory.createContact().as();
		object.setPhoneList(new ArrayList<PhoneDto>());

		editorDriver.initialize(view);
		editorDriver.edit(object);
		view.enableSave(true);
		done = false;

		panel.setWidget(view);
	}

	private void attach() {
		view.setHandler(viewHandler);
		view.getNameEditor().setHandler(nameEditorHandler);
	}

	private void detach() {
		view.setHandler(null);
		view.getNameEditor().setHandler(null);
	}
}
